package cn.clementine.core.entity;

import cn.clementine.core.utils.FixedSizeStringBuilder;
import com.pty4j.PtyProcess;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class Terminal extends Thread {
    String terminal_name;
    volatile OutputStream terminal_output_stream;
    volatile InputStream terminal_input_stream;
    volatile WebSocketSession terminal_session;
    volatile PtyProcess terminal_process;
    public Terminal(String terminal_name,OutputStream terminal_output_stream, InputStream terminal_input_stream, WebSocketSession terminal_session, PtyProcess terminal_process){
        super(terminal_name);
        this.terminal_name = terminal_name;
        this.terminal_output_stream = terminal_output_stream;
        this.terminal_input_stream = terminal_input_stream;
        this.terminal_session = terminal_session;
        this.terminal_process = terminal_process;
    }

    private final Object terminal_session_lock = new Object();
    StringBuilder cache = new StringBuilder();
    FixedSizeStringBuilder lastCache = new FixedSizeStringBuilder(2000);
    @Override
    public void run() {
        try {
            while (true) {
                byte[] buffer = new byte[1024];
                if(!cache.isEmpty()&&terminal_session.isOpen()) {
                    terminal_session.sendMessage(new TextMessage(cache.toString()));
                    terminal_session.sendMessage(new TextMessage(cache.toString()));
                    cache.delete(0, cache.length()-1);
                }
                int length = terminal_input_stream.read(buffer);
                if (length > 0) {
                    String part = new String(buffer, 0, length, StandardCharsets.UTF_8);
                    synchronized (terminal_session_lock) {
                        if (!terminal_session.isOpen()) {
                            cache.append(part);
                        }else {
                            lastCache.append(part);
                            terminal_session.sendMessage(new TextMessage(part));
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("Error reading from process output", e);
        }
    }
}
